﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Pacman.Simulator;
using Pacman.Simulator.Ghosts;

namespace PacmanAI
{
    abstract class MazeView<TCell>
    {
        private TCell[,] _cells;

        protected MazeView(Map m)
        {
            _cells = new TCell[m.Nodes.GetLength(0), m.Nodes.GetLength(1)];
            foreach (Node n in m.Nodes)
                AddNode(n);
        }

        protected MazeView(GameState gs) : this(gs.Map)
        {
            foreach (var g in gs.Ghosts)                
                AddGhost(g);
            AddNode(gs.Pacman.Node, PacmanToCell());
        }

        protected void AddNode(Node n, TCell r)
        {
            _cells[n.X, n.Y] = r;
        }

        public void AddGhost(Ghost g)
        {
            AddNode(g.Node,GhostToCell(g));
        }

        public void AddNode(Node n)
        {
            _cells[n.X, n.Y] = NodeToCell(n);
        }

        public void AddNodes(List<Node> nodes)
        {
            foreach (Node n in nodes)
                AddNode(n);
        }

        public void AddNodes(List<Node> nodes, TCell c)
        {
            foreach (Node n in nodes)
                AddNode(n,c);
        }

        protected abstract TCell NodeToCell(Node n);
        protected abstract TCell PacmanToCell();
        protected abstract TCell GhostToCell(Ghost g);

        public override string ToString()
        {
            StringBuilder b = new StringBuilder();
            b.AppendLine();
            for (int h = 0; h < _cells.GetLength(1); h++)
            {
                for (int w = 0; w < _cells.GetLength(0); w++)
                    b.Append(_cells[w, h].ToString());
                b.AppendLine();
            }
            return b.ToString();
        }
    }

    class CharView : MazeView<string>
    {
        private static string CharToString(char c)
        {
            return string.Format("{0}{1}", ' ', c);
        }

        public const string PATHCELL = " P";

        public CharView(Map m) : base(m) { }
        public CharView(GameState gs) : base(gs) {}

        private char NodeToChar(Node n)
        {
            switch (n.Type)
            {
                case Node.NodeType.Pill:
                    return '+';
                case Node.NodeType.PowerPill:
                    return 'O';
                case Node.NodeType.Wall:
                    return ' ';                
                default:
                    return '-';
            }
        }


        protected override string NodeToCell(Node n)
        {
            return CharToString(NodeToChar(n));
        }

        protected override string GhostToCell(Ghost g)
        {
            if (Ghost.MatchEdible(g))
                return CharToString('$');
            if (Ghost.MatchChasing(g))
                return CharToString('C');
            return CharToString('?');
        }

        protected override string PacmanToCell()
        {
            return CharToString('@');
        }
    }
}
